package com.daohang361.imqq.decoder;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import com.daohang361.imqq.Asycore.MyLoger;
import com.daohang361.imqq.Asycore.QQUser;
import com.daohang361.imqq.protocol.QQ2011;
import com.daohang361.imqq.tool.Hex2Bytes;
import com.daohang361.imqq.tool.MyByteReciveArray;
import com.daohang361.imqq.tool.MyUtil;
import com.daohang361.imqq.tool.WriteImg;
/**
 * 基本登陆命令核心解析
 * @author naner
 */
public class LoginDecoder implements InterfaceDecoder {
	private MyByteReciveArray myArray;
	private QQUser sessionQQ;
	public LoginDecoder(MyByteReciveArray myArray,QQUser sessionQQ){
		this.myArray=myArray;
		this.sessionQQ=sessionQQ;
	}
	/**
	 * 登陆命令解析
	 * @return 封装的QQUser
	 * @throws 解析失败异常则登陆包不前进，则就会继续发送本次
	 */
	public QQUser  decode() throws Exception{
		int command = myArray.getCommand();
		try {
			if (command == QQ2011.QQ_PROTOCOL_LOGIN_1) {
				myArray.decryptRemain(QQ2011.QQ_LOGIN_FIX_91_key);
				myArray.extract(0, 0);
				myArray.save();
				byte[] loginTime = myArray.extract(0, 3);//登陆时间
				sessionQQ.addAttr("loginTime", loginTime);
				myArray.save();
				byte[] ipByte = myArray.extract(0, 3);//登陆IP
			System.out.println("登陆IP：" + MyUtil.bytes2IP(ipByte));
				sessionQQ.addAttr("loginIp", ipByte);
				myArray.save();
				myArray.extract(0, 7);
				myArray.delete();
				byte[] token_91_length = myArray.extract(0, 1);//0091_Token长度：56字节
				sessionQQ.addAttr("token_91_length", token_91_length);
				myArray.save();
				byte[] Token91_data = myArray.extract(0, 55);
				System.out.println("Token91_data:"+ Hex2Bytes.bytesToHexString(Token91_data));
				myArray.save();
				sessionQQ.addAttr("Token91_data", Token91_data);
			byte[] isRedirect=myArray.extract(0, 0);
				myArray.delete();
			if(MyUtil.byte2Int(isRedirect[0])==1)
				{
			
					myArray.extract(0, 8);
					myArray.delete();
					byte[] redirectIp=myArray.extract(0	, 3);
					System.out.println("需要重定向到服务器:"+MyUtil.bytes2IP(redirectIp));
					sessionQQ.addAttr("redirectIp", redirectIp);
					sessionQQ.setLogintimes(-1);//登陆包后退抵消后面前进,使其返回为0
				}
			} else if (command == QQ2011.QQ_PROTOCOL_LOGIN_2) {
				myArray.decryptRemain(QQ2011.QQ_LOGIN_FIX_BA_key);
				/**
				 *普通无验证码        03 00 05 00 00 00 00 00
				 *图片验证成功        04 00 05 00 00 00 00 00 
				 *图片验证失败        04 00 05 01 00 00 01 23失败获取partimg1
				 *验证码图片1/2  03 00 05 01 00 00 01 21 
				 *
				 */
				byte[] checkResult=myArray.extract(0, 0);//是否需要验证码.03:成功 04:需要验证码成功
				myArray.delete();
				myArray.extract(0, 1);
			    byte[] isCechek=myArray.extract(0, 0);//0不需要，1需要,通过次flag判断验证是否成功
			    sessionQQ.addAttr("isCechek", isCechek);
				myArray.extract(0, 3);
				myArray.delete();
				byte[] token_ba_length = myArray.extract(0, 1);//00BA_Token长度：没验证码时候56字节，有的时候30字节
				myArray.delete();
				sessionQQ.addAttr("token_ba_length", token_ba_length);
				byte[] TokenBA_data = myArray.extract(0, MyUtil.bytes2Integer(token_ba_length)-1);
				sessionQQ.addAttr("TokenBA_data", TokenBA_data);
				//如果有图片验证的时候次data数据会被最后的data覆盖,而实际上带验证码请求包携带数据也为最后次data
			System.out.println("TokenBA_data:"+ Hex2Bytes.bytesToHexString(TokenBA_data));
				myArray.delete();
				if(MyUtil.bytes2Integer(isCechek)==1){//属于图片处理部分
					System.out.println("图片验证处理");
					//需要验证码03而且不是返回验证码成功04的特殊处理,如果为04则正常转向dd命令
					int imgLength=MyUtil.bytes2Integer(myArray.extract(0, 1));	
					byte[] imgPart=myArray.extract(0, imgLength-1);
					byte[] Squence=myArray.extract(0, 0);//图片包序号
					int imgSquence=MyUtil.bytes2Integer(Squence);//
					byte[] imgFlag =myArray.extract(0, 0);//是否结束 01表示还要 00表示结束
					int imgEndFlag=MyUtil.bytes2Integer(imgFlag);
					byte[] imgDataLeng=myArray.extract(0, 1);
				    int imgDataLength=MyUtil.bytes2Integer(imgDataLeng);
					byte[] imgData=myArray.extract(0, imgDataLength-1);
					sessionQQ.addAttr("imgFlag", imgFlag);//设置是否结束标识，用于辅助发送包
					sessionQQ.addAttr("Squence", Squence);//设置当前序号标识，用于辅助发送包
					sessionQQ.addAttr("imgDataLeng"+imgSquence, imgDataLeng);//设置当前序号标识，用于辅助发送包
					sessionQQ.addAttr("imgPart"+imgSquence, imgPart);//图片数据
					sessionQQ.addAttr("imgData"+imgSquence, imgData);//携带数据
					
					if(imgEndFlag==QQ2011.QQ_LOGIN_BA_IMGEND_FLAG){//最后一个img包了
						byte[] imgTotal=new byte[0];
						for(int i=0;i<=imgSquence;i++){
							byte[] temp1=sessionQQ.getAttr("imgPart"+(i));
							int oldLenth=imgTotal.length;
							byte[] imgTotalTemp=new byte[oldLenth+temp1.length];
							System.arraycopy(imgTotal, 0, imgTotalTemp, 0, oldLenth);
							System.arraycopy(temp1, 0, imgTotalTemp, oldLenth, temp1.length);
							imgTotal=imgTotalTemp;
						}
						sessionQQ.addAttr("imgTotal", imgTotal);
						System.out.println("总图片为:");
						MyLoger.printByteToHex(Hex2Bytes.bytesToHexString(imgTotal));
						try {
							WriteImg.writeCheck(imgTotal, sessionQQ.getQq());
							sessionQQ.addAttr("CinCeckCodeState", MyUtil.int2Bytes(QQ2011.QQ_LOGIN_BA_IMG_WAIT_IN));//设置img checkcode状态为等待
						} catch (Exception e) {
							System.out.println("写入文件失败!");
							e.printStackTrace();
						}
						int checkCodeState=0;
						
						System.out.println(("请打开"+sessionQQ.getQq()+"，并且在这里输入其中的字符串，然后回车："));
						InputStreamReader ins = new InputStreamReader(System.in);
						BufferedReader br = new BufferedReader(ins);
						String check = br.readLine();	
						byte[] checkCodeLength=new byte[]{0x00,0x04};
						sessionQQ.addAttr("checkCode", check.getBytes());
						sessionQQ.addAttr("checkCodeLength", checkCodeLength);
						sessionQQ.addAttr("CinCeckCodeState", new byte[]{(byte)QQ2011.QQ_LOGIN_BA_IMG_IN_DONE});
						
						while(true){
							checkCodeState=MyUtil.bytes2Integer(sessionQQ.getAttr("CinCeckCodeState"));
							if(checkCodeState==QQ2011.QQ_LOGIN_BA_IMG_WAIT_IN){
								Thread.sleep(1000);//继续等待
							}else if(checkCodeState==QQ2011.QQ_LOGIN_BA_IMG_CHANGE){//更改图片
								//do something
								clearImgEnvironment();
								break;
							}else if(checkCodeState==QQ2011.QQ_LOGIN_BA_IMG_IN_DONE){//图片输入完毕
								//do something
								clearImgEnvironment();
								break;
							}
						}
					}
					sessionQQ.setLogintimes(sessionQQ.getLogintimes()-1);//凡是涉及到验证图片的都需要重新发送ba包，登陆包后退抵消后面
				}else if(MyUtil.bytes2Integer(checkResult)==QQ2011.QQ_LOGIN_BA_IMG_CHECK_SUCCESS&&MyUtil.bytes2Integer(isCechek)==0){//验证码成功
					
				}
			} else if (command == QQ2011.QQ_PROTOCOL_LOGIN_3) {//0xdd
				myArray.decryptRemain(QQ2011.QQ_LOGIN_FIX_DD_NEXT_KEY);
				myArray.extract(0, 1);//数据长度
				myArray.delete();
				byte[] isSuccess = myArray.extract(0, 0);//00 //成功，（00验证通过、33或51拒绝登录、BF没有该QQ号、34密码错误）
				if(Hex2Bytes.bytesToHexString(isSuccess).equalsIgnoreCase("34")){
					System.out.println("密码错误!!");
					System.exit(1);
				}
				sessionQQ.addAttr("isSuccess", isSuccess);
				myArray.delete();
				myArray.extract(0, 1);
				myArray.delete();
				byte[] TokenDD_1 = myArray.extract(0, 31);//TokenDD_1
				sessionQQ.addAttr("TokenDD_1", TokenDD_1);
			System.out.println("TokenDD_1:"+ Hex2Bytes.bytesToHexString(TokenDD_1));
				myArray.delete();
				myArray.extract(0, 9);
				myArray.delete();
				byte[] TokenDD_2 = myArray.extract(0, 143);//TokenDD_2
				sessionQQ.addAttr("TokenDD_2", TokenDD_2);
				System.out.println("TokenDD_2:"+ Hex2Bytes.bytesToHexString(TokenDD_2));
				myArray.delete();
				myArray.extract(0, 1);
				myArray.delete();
				byte[] TokenDD_3 = myArray.extract(0, 55);//TokenDD_3
				sessionQQ.addAttr("TokenDD_3", TokenDD_3);
			System.out.println("TokenDD_3:"+ Hex2Bytes.bytesToHexString(TokenDD_3));
				myArray.delete();
				byte[] TokenDD_key1 = myArray.extract(0, 15);//TokenDD_key1
				sessionQQ.addAttr("TokenDD_key1", TokenDD_key1);
			System.out.println("TokenDD_key1:"+ Hex2Bytes.bytesToHexString(TokenDD_key1));
				myArray.delete();
				myArray.extract(0, 1);
				myArray.delete();
				byte[] TokenDD_key2 = myArray.extract(0, 15);//TokenDD_key2
				sessionQQ.addAttr("TokenDD_key2", TokenDD_key2);
			System.out.println("TokenDD_key2:"+ Hex2Bytes.bytesToHexString(TokenDD_key2));
				myArray.delete();
				myArray.extract(0, 1);
				myArray.delete();
				if (isSuccess[0] == 0) {
					System.out.println("0xDD:登陆成功!");
				}else{
					throw new Exception("0xDD:登陆失败!");
				}

			} else if (command == QQ2011.QQ_PROTOCOL_LOGIN_4) {//0xe5
				byte temp[] =myArray.decryptRemain(sessionQQ.getAttr("TokenDD_key2"));
				if(temp==null)
					{
					myArray.decryptRemain(sessionQQ.getAttr("TokenDD_key1"));
					System.out.println("网络环境发生变化,为了你的账号安全，重新登录!");
					sessionQQ.setLogintimes(0);
					QQ2011.RandomKey();
					return sessionQQ;
					}
				myArray.extract(0, 3);
				myArray.delete();
				byte[] TokenE5_key1 = myArray.extract(0, 15);
				sessionQQ.addAttr("TokenE5_key1", TokenE5_key1);
			System.out.println("TokenE5_key1:"+ Hex2Bytes.bytesToHexString(TokenE5_key1));
				myArray.delete();
				myArray.extract(0, 7);
				myArray.delete();
				byte[] TokenE5_fix = myArray.extract(0, 3);
				sessionQQ.addAttr("TokenE5_fix", TokenE5_fix);
			System.out.println("TokenE5_fix:"+ Hex2Bytes.bytesToHexString(TokenE5_fix));
				myArray.delete();
				myArray.extract(0, 17);
				myArray.delete();
				byte[] TokenE5_data1 = myArray.extract(0, 207);
				sessionQQ.addAttr("TokenE5_data1", TokenE5_data1);
			System.out.println("TokenE5_data1:"+ Hex2Bytes.bytesToHexString(TokenE5_data1));
				myArray.delete();

				byte[] TokenE5_key2 = myArray.extract(0, 15);
				sessionQQ.addAttr("TokenE5_key2", TokenE5_key2);
			System.out.println("TokenE5_key2:"+ Hex2Bytes.bytesToHexString(TokenE5_key2));
				myArray.delete();

				myArray.extract(0, 1);
				myArray.delete();
				byte[] TokenE5_data2 = myArray.extract(0, 119);
				sessionQQ.addAttr("TokenE5_data2", TokenE5_data2);
			System.out.println("TokenE5_data2:"+ Hex2Bytes.bytesToHexString(TokenE5_data2));
				myArray.delete();
				myArray.extract(0, 16);
				myArray.delete();
				byte[] tokenE5_key = myArray.extract(0, 15);
				sessionQQ.addAttr("tokenE5_key", tokenE5_key);
			System.out.println("tokenE5_key:"+ Hex2Bytes.bytesToHexString(tokenE5_key));
				myArray.extract(0, 9);
				myArray.delete();
				byte[] TokenE5_data3 = myArray.extract(0, 87);
				sessionQQ.addAttr("TokenE5_data3", TokenE5_data3);
			System.out.println("TokenE5_data3:"+ Hex2Bytes.bytesToHexString(TokenE5_data3));
				myArray.extract(0, 1);
				myArray.delete();
			} else if (command == QQ2011.QQ_PROTOCOL_LOGIN_5) {//0xe3 获取昵称
				myArray.decryptRemain(sessionQQ.getAttr("TokenE5_key2"));
				myArray.extract(0, 6);
				myArray.delete();
				byte[] ninameLength = myArray.extract(0, 0);
				int nameLength = MyUtil.byte2Int(ninameLength[0]);
				byte[] niname = myArray.extract(0, nameLength - 1);
				String myName = new String(niname, "UTF-8");
			System.out.println("myName:" + myName);
				sessionQQ.addAttr("niname", niname);
			} else if (command == QQ2011.QQ_PROTOCOL_LOGIN_6) {//0x30
				byte[] temp=myArray.decryptRemain(sessionQQ.getAttr("TokenE5_key1"));
				if(temp==null)
					{
					myArray.decryptRemain(sessionQQ.getAttr("TokenE5_key1"));
					System.out.println("网络环境发生变化,为了你的账号安全，重新登录!");
					sessionQQ.setLogintimes(0);
					QQ2011.RandomKey();
					return sessionQQ;
					}else
					{
					myArray.extract(0, 0);
					myArray.delete();
					byte[] SessionKey = myArray.extract(0, 15);
					sessionQQ.addAttr("SessionKey", SessionKey);
					sessionQQ.setSessionkey(Hex2Bytes.bytesToHexString(SessionKey));
					System.out.println("SessionKey:"+ Hex2Bytes.bytesToHexString(SessionKey));
					myArray.delete();
					myArray.extract(0, 7);
					myArray.delete();
					byte[] unkown_30_data1 = myArray.extract(0, 5);
					myArray.delete();
					System.out.println("unkown_30_data1:"+ Hex2Bytes.bytesToHexString(unkown_30_data1));
					myArray.extract(0, 47);
					myArray.delete();
					byte[] Token30_data = myArray.extract(0, 47);
					sessionQQ.addAttr("Token30_data", Token30_data);
					myArray.delete();
					System.out.println("Token30_data:"+ Hex2Bytes.bytesToHexString(Token30_data));
					byte[] unkown_30_data2 = myArray.extract(0, 7);
					sessionQQ.addAttr("unkown_30_data2", unkown_30_data2);
					myArray.delete();
					System.out.println("unkown_30_data2:"+ Hex2Bytes.bytesToHexString(unkown_30_data2));
					myArray.extract(0, 3);
					myArray.delete();
					System.out.println("0x30 times:"+sessionQQ.getLogintimes());
					}
				}
		} catch (Exception e) {
			
			e.printStackTrace();
			int loginFails = 
				null==sessionQQ.getAttr("loginFails")?0:MyUtil.bytes2Integer(sessionQQ.getAttr("loginFails"));
			if(loginFails==3)
				{
				System.out.println("command:0x"+Integer.toHexString(command)+"转换失败请检查账号密码!");;
				sessionQQ.setLogintimes(-2);//session中止
				}else
				{
					System.out.println("command:0x"+Integer.toHexString(command)+"转换失败!继续本轮");
					loginFails++;
					sessionQQ.setLogintimes(0);
					sessionQQ.addAttr("loginFails",MyUtil.int2Bytes(loginFails));
				}
			return sessionQQ;
		}
			sessionQQ.setLogintimes(sessionQQ.getLogintimes()+1);//登陆包前进
			sessionQQ.setPakage(sessionQQ.getPakage()+1);//登陆包自动增长
		return sessionQQ;
	}
	@Override
	public void init(MyByteReciveArray myArray, QQUser sessionQQ) {
		// TODO Auto-generated method stub
		
	}
	private void clearImgEnvironment(){
		
	}
	@Override
	public Object invoke(Object... o) {
		// TODO Auto-generated method stub
		return null;
	}
}
